{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import pandas as pd\n",
    "import matplotlib.pyplot as plt"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(160, 2) (160,) (40, 2) (40,)\n"
     ]
    }
   ],
   "source": [
    "mean1, mean2 = np.array([-1, 2]), np.array([1, -1])\n",
    "mean3, mean4 = np.array([4, -4]), np.array([-4, 4])\n",
    "covar = np.array([[1.0, 0.8], [0.8, 1.0]])\n",
    "X1 = np.random.multivariate_normal(mean1, covar, 50)\n",
    "X1 = np.vstack((X1, np.random.multivariate_normal(mean3, covar, 50)))\n",
    "y1 = np.ones(X1.shape[0])\n",
    "X2 = np.random.multivariate_normal(mean2, covar, 50)\n",
    "X2 = np.vstack((X2, np.random.multivariate_normal(mean4, covar, 50)))\n",
    "y2 = -1 * np.ones(X2.shape[0])\n",
    "X_train = np.vstack((X1[:80], X2[:80]))\n",
    "y_train = np.hstack((y1[:80], y2[:80]))\n",
    "X_test = np.vstack((X1[80:], X2[80:]))\n",
    "y_test = np.hstack((y1[80:], y2[80:]))\n",
    "print(X_train.shape, y_train.shape, X_test.shape, y_test.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 设置颜色参数\n",
    "colors = {1:'r', -1:'g'}\n",
    "# 绘制二分类数据集的散点图\n",
    "plt.scatter(X_train[:,0], X_train[:,1], marker='o', c=pd.Series(y_train).map(colors))\n",
    "plt.show();"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [],
   "source": [
    "### 定义高斯核函数\n",
    "def gaussian_kernel(x1, x2, sigma=5.0):\n",
    "    '''\n",
    "    输入:\n",
    "    x1: 向量1\n",
    "    x2: 向量2\n",
    "    输出:\n",
    "    两个向量的高斯核\n",
    "    '''\n",
    "    return np.exp(-1 * np.linalg.norm(x1-x2)**2 / (2 * (sigma ** 2)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [],
   "source": [
    "from cvxopt import matrix, solvers\n",
    "\n",
    "### 定义线性不可分支持向量机\n",
    "### 借助于高斯核函数转化为线性可分的情形\n",
    "class Non_Linear_SVM:\n",
    "    ### 定义基本参数\n",
    "    def __init__(self, kernel=gaussian_kernel):\n",
    "        # 非线性可分svm核函数，默认为高斯核函数\n",
    "        self.kernel = kernel\n",
    "    \n",
    "    ### 定义非线性可分支持向量机拟合方法\n",
    "    def fit(self, X, y):\n",
    "        # 训练样本数和特征数\n",
    "        m, n = X.shape\n",
    "        \n",
    "        # 基于线性核计算Gram矩阵\n",
    "        K = self._gram_matrix(X)\n",
    "                \n",
    "        # 初始化二次规划相关变量：P/q/A/b/G/h\n",
    "        P = matrix(np.outer(y,y) * K)\n",
    "        q = matrix(np.ones(m) * -1)\n",
    "        A = matrix(y, (1, m))\n",
    "        b = matrix(0.0)\n",
    "        G = matrix(np.diag(np.ones(m) * -1))\n",
    "        h = matrix(np.zeros(m))\n",
    "\n",
    "        # 构建二次规划求解\n",
    "        sol = solvers.qp(P, q, G, h, A, b)\n",
    "        # 拉格朗日乘子\n",
    "        a = np.ravel(sol['x'])\n",
    "\n",
    "        # 寻找支持向量\n",
    "        spv = a > 1e-5\n",
    "        ix = np.arange(len(a))[spv]\n",
    "        self.a = a[spv]\n",
    "        self.spv = X[spv]\n",
    "        self.spv_y = y[spv]\n",
    "        print('{0} support vectors out of {1} points'.format(len(self.a), m))\n",
    "\n",
    "        # 截距向量\n",
    "        self.b = 0\n",
    "        for i in range(len(self.a)):\n",
    "            self.b += self.spv_y[i]\n",
    "            self.b -= np.sum(self.a * self.spv_y * K[ix[i], spv])\n",
    "        self.b /= len(self.a)\n",
    "\n",
    "        # 权重向量\n",
    "        self.w = None\n",
    "\n",
    "    ### 定义Gram矩阵计算函数\n",
    "    def _gram_matrix(self, X):\n",
    "        m, n = X.shape\n",
    "        K = np.zeros((m, m))\n",
    "        # 遍历计算Gram矩阵\n",
    "        for i in range(m):\n",
    "            for j in range(m):\n",
    "                K[i,j] = self.kernel(X[i], X[j])\n",
    "        return K\n",
    "    \n",
    "    ### 定义映射函数\n",
    "    def project(self, X):\n",
    "        y_pred = np.zeros(len(X))\n",
    "        for i in range(X.shape[0]):\n",
    "            s = 0\n",
    "            for a, spv_y, spv in zip(self.a, self.spv_y, self.spv):\n",
    "                s += a * spv_y * self.kernel(X[i], spv)\n",
    "            y_pred[i] = s\n",
    "        return y_pred + self.b\n",
    "    \n",
    "    ### 定义模型预测函数\n",
    "    def predict(self, X):\n",
    "        return np.sign(self.project(X))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "     pcost       dcost       gap    pres   dres\n",
      " 0: -5.3110e+01 -1.6223e+02  4e+02  2e+01  2e+00\n",
      " 1: -8.0716e+01 -1.8786e+02  2e+02  5e+00  7e-01\n",
      " 2: -1.0556e+02 -1.9757e+02  1e+02  3e+00  4e-01\n",
      " 3: -1.7380e+02 -2.7165e+02  1e+02  3e+00  4e-01\n",
      " 4: -2.4244e+02 -2.8787e+02  6e+01  9e-01  1e-01\n",
      " 5: -2.5720e+02 -2.6511e+02  9e+00  1e-01  1e-02\n",
      " 6: -2.6014e+02 -2.6216e+02  2e+00  1e-02  2e-03\n",
      " 7: -2.6162e+02 -2.6165e+02  3e-02  2e-04  2e-05\n",
      " 8: -2.6164e+02 -2.6164e+02  3e-04  2e-06  2e-07\n",
      " 9: -2.6164e+02 -2.6164e+02  3e-06  2e-08  2e-09\n",
      "Optimal solution found.\n",
      "9 support vectors out of 160 points\n",
      "Accuracy of soft margin svm based on cvxopt:  1.0\n"
     ]
    }
   ],
   "source": [
    "# 导入sklearn准确率评估函数\n",
    "from sklearn.metrics import accuracy_score\n",
    "# 创建非线性可分支持向量机模型实例\n",
    "non_linear_svm = Non_Linear_SVM()\n",
    "# 模型拟合\n",
    "non_linear_svm.fit(X_train, y_train)\n",
    "# 模型预测\n",
    "y_pred = non_linear_svm.predict(X_test)\n",
    "# 计算测试集准确率\n",
    "print('Accuracy of soft margin svm based on cvxopt: ', \n",
    "      accuracy_score(y_test, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "### 绘制非线性可分支持向量机\n",
    "def plot_classifier(X1_train, X2_train, clf):\n",
    "    plt.plot(X1_train[:,0], X1_train[:,1], \"ro\")\n",
    "    plt.plot(X2_train[:,0], X2_train[:,1], \"go\")\n",
    "    plt.scatter(non_linear_svm.spv[:,0], non_linear_svm.spv[:,1], \n",
    "                s=100, c=\"\", edgecolors=\"b\", label=\"support vector\")\n",
    "\n",
    "    X1, X2 = np.meshgrid(np.linspace(-4,4,50), np.linspace(-4,4,50))\n",
    "    X = np.array([[x1, x2] for x1, x2 in zip(np.ravel(X1), np.ravel(X2))])\n",
    "    Z = non_linear_svm.project(X).reshape(X1.shape)\n",
    "    plt.contour(X1, X2, Z, [0.0], colors='k', linewidths=1, origin='lower')\n",
    "    plt.contour(X1, X2, Z + 1, [0.0], colors='grey', linewidths=1, origin='lower')\n",
    "    plt.contour(X1, X2, Z - 1, [0.0], colors='grey', linewidths=1, origin='lower')\n",
    "    plt.legend()\n",
    "    plt.show()\n",
    "    \n",
    "plot_classifier(X_train[y_train==1], X_train[y_train==-1], non_linear_svm)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Accuracy of soft margin svm based on sklearn:  1.0\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "D:\\Installation\\anaconda\\install\\lib\\site-packages\\sklearn\\svm\\base.py:196: FutureWarning: The default value of gamma will change from 'auto' to 'scale' in version 0.22 to account better for unscaled features. Set gamma explicitly to 'auto' or 'scale' to avoid this warning.\n",
      "  \"avoid this warning.\", FutureWarning)\n"
     ]
    }
   ],
   "source": [
    "from sklearn import svm\n",
    "# 创建svm模型实例\n",
    "clf = svm.SVC(kernel='rbf')\n",
    "# 模型拟合\n",
    "clf.fit(X_train, y_train)\n",
    "# 模型预测\n",
    "y_pred = clf.predict(X_test)\n",
    "# 计算测试集准确率\n",
    "print('Accuracy of soft margin svm based on sklearn: ', \n",
    "      accuracy_score(y_test, y_pred))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
